﻿using System;
using System.Collections.Generic;
using ProjectDanmaku.Core;
using ProjectDanmaku.Entity.Manipulator;
using ProjectDanmaku.Scenario;
using ProjectDanmaku.Util;
using UnityEngine;

namespace ProjectDanmaku.Entity.SubLayer.EnemyBullet
{
    public class SimpleBulletSubLayer : EntitySubLayer
    {
        private uint _collideLayerMask = BitUtility.All;

        [SerializeField] private Sprite bulletSprite;
        [SerializeField] private int bulletColliderPixelRadius;

        protected SimpleMotionManipulator _simpleMotionManipulator = new();
        protected ScreenBoundCheckManipulator _screenBoundCheckManipulator = new();
        protected ShootableCollidePhysicsManipulator _shootableCollidePhysicsManipulator = new();
        protected DeathZoneCheckManipulator _deathZoneCheckManipulator = new();

        private Mesh _mesh;

        private void Start()
        {
            Material.SetTexture("_MainTex", bulletSprite.texture);
            
            _shootableCollidePhysicsManipulator.SetLayerMask(_collideLayerMask);
            _shootableCollidePhysicsManipulator.SetColliderRadius(CoordUtility.PixelToUnit(bulletColliderPixelRadius));
            
            _mesh = MeshUtility.SpriteToMesh(bulletSprite);
        }

        public void SetCollideLayerMask(uint layerMask)
        {
            this._collideLayerMask = layerMask;
            
            _shootableCollidePhysicsManipulator.SetLayerMask(layerMask);
        }

        public override Type GetEntityDataType()
        {
            return typeof(EntityData);
        }

        public override Mesh GetSpriteMesh()
        {
            return _mesh;
        }

        protected override void EntityLogicTick(EntityData data)
        {
            _simpleMotionManipulator.Do(data);
            _screenBoundCheckManipulator.Do(data);
        }

        protected override void EntityPhysicsTick(EntityData data)
        {
            _shootableCollidePhysicsManipulator.Do(data);
        }

        protected override void EntityLateTick(EntityData data)
        {
            _deathZoneCheckManipulator.Do(data);
        }

        protected override void EntityInit(EntityData data)
        {
            
        }

        protected void SetNewSprite(Sprite sprite)
        {
            bulletSprite = sprite;
            DestroyImmediate(_mesh, true);
            _mesh = MeshUtility.SpriteToMesh(sprite);
        }

        public virtual void Shoot(Vector2 position, float velocity, float rotInDegree)
        {
            var v = new Vector2(0, 1);
            v = MathHelper.RotateVec2(v, rotInDegree) * velocity;
            
            AddEntity(new EntityData
            {
                Position = position,
                RotateZ = rotInDegree * Mathf.Deg2Rad,
                Velocity = v
            });
        }
    }
}